﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone

using BlazorAdmin.Caching;
using BlazorAdmin.Models;
using BlazorAdmin.Interface;
using BlazorAdmin.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using BlazorAdmin.Services.DbService;

namespace BlazorAdmin.Services
{
    internal class GroupService : BaMgmtDbService, IGroup
    {
        private const string GroupServiceGetAllCacheKey = "GroupService-GetAll";
        private const string GroupServiceGetGroupsByUserIdCacheKey = "GroupService-GetGroupsByUserId";
        private const string GroupServiceGetGroupsByRoleIdCacheKey = "GroupService-GetGroupsByRoleId";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="db"></param>
        public GroupService(IPetaPoco db) : base(db) { }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public List<SysGroup> GetAll() => CacheManager.GetOrAdd(GroupServiceGetAllCacheKey, entry => Fetch<SysGroup>());

        /// <summary>
        /// 
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<int> GetGroupsByUserId(int userId)
        {
            return CacheManager.GetOrAdd($"{GroupServiceGetGroupsByUserIdCacheKey}-{userId}",
                entry => Fetch<int>("SELECT GroupID FROM UserGroup WHERE UserID = @0", userId));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="groupIds"></param>
        /// <returns></returns>
        public bool SaveGroupsByUserId(int userId, IEnumerable<int> groupIds)
        {
            var ret = false;
            using var db = Create();
            try
            {
                db.BeginTransaction();
                db.Execute("DELETE FROM UserGroup WHERE UserID = @0", userId);
                db.InsertBatch("UserGroup", groupIds.Select(g => new { GroupID = g, UserID = userId }));
                db.CompleteTransaction();
                ret = true;
            }
            catch (Exception)
            {
                db.AbortTransaction();
                throw;
            }
            if (ret)
            {
                CacheManager.Clear();
            }
            return ret;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public List<int> GetGroupsByRoleId(int roleId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByRoleIdCacheKey}-{roleId}",
            entry => Fetch<int>("SELECT GroupID FROM RoleGroup WHERE RoleID = @0", roleId));

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="groupIds"></param>
        /// <returns></returns>
        public bool SaveGroupsByRoleId(int roleId, IEnumerable<int> groupIds)
        {
            var ret = false;
            using var db = Create();
            try
            {
                db.BeginTransaction();
                db.Execute("DELETE FROM RoleGroup WHERE RoleID = @0", roleId);
                db.InsertBatch("RoleGroup", groupIds.Select(g => new { GroupID = g, RoleID = roleId }));
                db.CompleteTransaction();
                ret = true;
            }
            catch (Exception)
            {
                db.AbortTransaction();
                throw;
            }

            if (ret)
            {
                CacheManager.Clear();
            }
            return ret;
        }
    }
}